package com.cgmnx.admin.dao.entity.rbac;


import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

@Slf4j
@Setter
@Getter
@ToString
@Service
public class ResourceTree extends ResourceEntity {

    private List<ResourceTree> children = Lists.newArrayList();

    /**
     * 节点层级
     */
    private int nodeLevel;

    /**
     * 节点是否被选中, 在绑定权限页面使用
     */
    private boolean checked = false;

    /**
     * 节点是否自动展开
     */
    private boolean open = false;

    private boolean hasChild = false;

    private Integer nodeCount;

    private Boolean isParent = false;

    private void addChild(ResourceTree node) {
        children.add(node);
    }

    /**
     * 根据parentId构建资源树
     *
     * @param resourceEntityList
     * @param parentId
     * @return
     */
    public List<ResourceTree> buildTree(List<ResourceEntity> resourceEntityList, int parentId) {
        return build(resourceEntityList, parentId);
    }


    /**
     * 构造树
     *
     * @param uriList
     * @return
     */
    public List<ResourceTree> buildTree(List<ResourceEntity> uriList) {
        return build(uriList, TOP_PARENT_ID);
    }

    private List<ResourceTree> build(List<ResourceEntity> uriList, int parentId) {

        long start = System.currentTimeMillis();
        boolean needTopUri = false;// 是否需要包含parentId该节点

        if (parentId == 0) {
            needTopUri = false;
        }

        if (CollectionUtils.isEmpty(uriList)) {
            return Collections.emptyList();
        }

        // 存放所有节点
        List<ResourceTree> nodeList = Lists.newArrayList();
        // 存放顶级节点
        List<ResourceTree> rootList = Lists.newArrayList();
        // 存放所有节点映射
        Map<Integer, ResourceTree> nodeMap = Maps.newLinkedHashMap();

        Iterator<ResourceEntity> it = uriList.iterator();
        while (it.hasNext()) {
            ResourceEntity uri = it.next();
            ResourceTree node = convertTreeNode(uri);
            int uriId = uri.getId();
            if (!needTopUri) {
                uriId = uri.getParentId();
            }
            if (uriId == parentId) { // 构造的树中包含当前节点
                rootList.add(node);
            } else {
                nodeList.add(node);
            }
            nodeMap.put(node.getId(), node);
        }

        for (ResourceTree rn : nodeList) {
            ResourceTree partNode = nodeMap.get(rn.getParentId());
            if (partNode != null) {
                partNode.setHasChild(true);
                partNode.addChild(rn);
            }
        }

        log.info("create tree use {} ms!", System.currentTimeMillis() - start);
        return rootList;
    }

    /**
     * 构建树包含是否选中的状态
     *
     * @param uriList
     * @param usiIdList
     * @return
     */
    public List<ResourceTree> buildTreeContainSelectedTag(List<ResourceEntity> uriList, List<Integer> usiIdList) {
        long start = System.currentTimeMillis();

        if (uriList == null) {
            return Collections.emptyList();
        }
        // 存放所有节点
        List<ResourceTree> nodeList = Lists.newArrayList();
        // 存放顶级节点
        List<ResourceTree> rootList = Lists.newArrayList();
        // 存放所有节点映射
        Map<Integer, ResourceTree> nodeMap = Maps.newHashMap();
        // 存放已绑定的uriMap
        Map<Integer, Integer> bindedUriIdMap = Maps.newHashMap();

        for (Integer uirId : usiIdList) {
            bindedUriIdMap.put(uirId, uirId);
        }

        Iterator<ResourceEntity> it = uriList.iterator();
        while (it.hasNext()) {
            ResourceEntity uri = it.next();
            ResourceTree node = convertTreeNode(uri);

            if (bindedUriIdMap.get(uri.getId()) != null) {
                node.setChecked(true);
                node.setOpen(true); // 选中的节点默认展开
            }

            if (uri.getParentId() == TOP_PARENT_ID) {
                rootList.add(node);
            } else {
                nodeList.add(node);
            }
            nodeMap.put(node.getId(), node);
        }

        for (ResourceTree rn : nodeList) {
            ResourceTree partNode = nodeMap.get(rn.getParentId());
            if (partNode != null) {
                partNode.addChild(rn);
            }
        }

        log.info("create tree use {} ms!", System.currentTimeMillis() - start);
        return rootList;
    }

    /**
     * 构建树节点
     *
     * @param uriList
     * @param bindingUriIdList
     * @return (树节点list)
     */
    public List<ResourceTree> buildTreeNodeContainSelectedTag(List<ResourceEntity> uriList, List<Integer> bindingUriIdList) {

        long start = System.currentTimeMillis();

        if (uriList == null) {
            return Collections.emptyList();
        }

        // 存放所有节点
        List<ResourceTree> nodeList = Lists.newArrayList();
        // 存放已绑定的uriMap
        Map<Integer, Integer> bindingUriIdMap = Maps.newHashMap();

        for (Integer uirId : bindingUriIdList) {
            bindingUriIdMap.put(uirId, uirId);
        }

        Iterator<ResourceEntity> it = uriList.iterator();
        while (it.hasNext()) {
            ResourceEntity uri = it.next();
            ResourceTree node = convertTreeNode(uri);

            if (bindingUriIdMap.get(uri.getId()) != null) {
                node.setChecked(true);
                node.setOpen(true); // 选中的节点默认展开
            }
            nodeList.add(node);
        }

        log.info("create tree node use {} ms!", System.currentTimeMillis() - start);
        return nodeList;
    }

    private ResourceTree convertTreeNode(ResourceEntity uri) {
        ResourceTree node = new ResourceTree();
        node.setId(uri.getId());
        node.setParentId(uri.getParentId());
        node.setName(uri.getName());
        node.setUri(uri.getUri());
        node.setTreeCode(uri.getTreeCode());
        node.setSort(uri.getSort());
        node.setNodeCount(uri.getNodeCount());
        node.setIsParent(uri.getNodeCount() > 0);
        node.setShowType(uri.getShowType());
        node.setCreateTime(uri.getCreateTime());
        node.setUpdateTime(uri.getUpdateTime());
        node.setNodeLevel(StringUtils.split(uri.getTreeCode(), TREE_CODE_SEPARATOR).length);
        return node;
    }

}
